from django.contrib.auth import get_user_model, authenticate
from rest_framework import serializers
import re


class AuthorSerializer(serializers.ModelSerializer):
    # read_only
    class Meta:
        model = get_user_model()
        fields = ('id', 'email', 'nickname', 'avatar', 'sex')

    def to_representation(self, instance):
        # set sex to readable text
        ret = super().to_representation(instance)
        ret['sex'] = instance.get_sex_display()
        return ret


class BlogUserSerializer(serializers.ModelSerializer):
    """
    Used for register and query info
    """
    last_login = serializers.DateTimeField(format="%Y-%m-%d %H:%M", required=False)

    # no validator

    class Meta:
        model = get_user_model()
        fields = ('id', 'email', 'nickname', 'avatar', 'sex', 'is_author', 'is_superuser', 'last_login', 'last_active_ip')
        read_only_fields = ('is_author', 'is_superuser', 'last_login', 'last_active_ip')

    def to_representation(self, instance):
        # set sex to readable text
        ret = super().to_representation(instance)
        ret['sex'] = instance.get_sex_display()
        return ret

    def validate_email(self, value):
        email_reg = r'^([\w-]+)@([\w-]+)(\.[\w-]+)*\.(edu|net|com|cn|org)$'
        if re.search(email_reg, value):
            if get_user_model().objects.filter(email=value, is_active=True).exists():
                raise serializers.ValidationError(f'{value} has already be registered')
            else:
                return value
        else:
            raise serializers.ValidationError('邮箱格式错误')

    def create(self, validated_data):
        # 创建用户时默认是不活跃的
        user, _ = get_user_model().objects.get_or_create(**validated_data,
                                                         is_author=False, is_superuser=False, is_active=False)
        return user


class UserSerializer(serializers.Serializer):
    # only for read
    is_login = serializers.BooleanField(read_only=True, source="is_authenticated")
    user = BlogUserSerializer(read_only=True, source="*")

    def to_representation(self, instance):
        if not instance.is_authenticated:
            return {'is_login': False, 'user': None}
        else:
            return super().to_representation(instance)


class LoginSerializer(serializers.Serializer):
    # used for login
    email = serializers.EmailField()  # use email for username
    password = serializers.CharField(max_length=40, write_only=True)

    def validate(self, data):
        email = data.get('email')
        password = data.get('password')
        user = authenticate(email=email, password=password)
        if user is None:
            raise serializers.ValidationError('账号密码错误，或用户未激活')
        else:
            return data

    def update(self, instance, validated_data):
        # update last_active_ip field
        login_ip = validated_data.get('login_ip')
        if login_ip:
            instance.last_active_ip = login_ip
            instance.save()
        return instance


class RegisterSerializer(serializers.Serializer):
    email = serializers.EmailField(help_text='用户唯一标示', label='用户邮箱', max_length=255)
    password = serializers.CharField(label='用户密码', max_length=30, required=True)
    nickname = serializers.CharField(help_text='最多30个字符', label='昵称', max_length=30, required=False)
    avatar = serializers.ImageField(allow_null=True, label='头像', max_length=100, required=False)
    sex = serializers.ChoiceField(choices=[(0, '男'), (1, '女'), (2, '保密')], label='性别', required=False)

    def validate_email(self, value):
        email_reg = r'^([\w-]+)@([\w-]+)(\.[\w-]+)*\.(edu|net|com|cn|org)$'
        if re.search(email_reg, value):
            if get_user_model().objects.filter(email=value, is_active=True).exists():
                raise serializers.ValidationError(f'{value} 已经被注册')
            else:
                return value
        else:
            raise serializers.ValidationError('邮箱格式错误')

    def validate_password(self, value):
        if len(value) < 6:
            return serializers.ValidationError('密码至少6位')
        return value

    def create(self, validated_data):
        # do not use password for look up
        password = validated_data.pop('password')
        # 创建用户时默认是不活跃的
        user, _ = get_user_model().objects.update_or_create(**validated_data,
                                                            is_author=False, is_superuser=False, is_active=False)
        user.set_password(password)
        user.save()
        return user


class ActivationSerializer(serializers.Serializer):
    email = serializers.EmailField(help_text='用户唯一标示', label='用户邮箱', max_length=255, required=True)
    captcha = serializers.CharField(label='激活码', max_length=10, required=True)

    def validate_email(self, value):
        email_reg = r'^([\w-]+)@([\w-]+)(\.[\w-]+)*\.(edu|net|com|cn|org)$'
        if re.search(email_reg, value):
            if not get_user_model().objects.filter(email=value, is_active=False).exists():
                raise serializers.ValidationError(f'{value} 已被激活或不存在')
            else:
                return value
        else:
            raise serializers.ValidationError('邮箱格式错误')

    def validate_captcha(self, value):
        captcha_reg = r'\d+'
        if re.search(captcha_reg, value):
            return value
        else:
            return serializers.ValidationError('验证码只能是纯数字')

    def save(self):
        email = self.validated_data['email']
        user = get_user_model().objects.get(email=email)
        user.is_active = True
        user.save()
        return user


class UpdateSerializer(serializers.Serializer):
    sex = serializers.ChoiceField(choices=[(0, '男'), (1, '女'), (2, '保密')], label='性别', required=False)
    nickname = serializers.CharField(help_text='最多30个字符', label='昵称', max_length=30, required=False)
    avatar = serializers.ImageField(allow_null=True, label='头像', max_length=100, required=False)

    def validate_nickname(self, value):
        if len(value) < 3:
            raise serializers.ValidationError('昵称至少3个字符')
        return value

    def validate(self, data):
        sex = data.get('sex')
        nickname = data.get('nickname')
        avatar = data.get('avatar')
        if (not sex) and (not nickname) and (not avatar):
            raise serializers.ValidationError('至少需要更新一个信息')
        return data

    def update(self, instance, validated_data):
        instance.sex = validated_data.get('sex', instance.sex)
        instance.nickname = validated_data.get('nickname', instance.nickname)
        instance.avatar = validated_data.get('avatar', instance.avatar)
        instance.save()
        return instance
